#ifndef __UTIL__POINT_HPP__
#define __UTIL__POINT_HPP__

#include <iostream>

namespace util {
  /** @brief A 3-component point or vector of doubles. */
  class point {
  public:
    point(double x = double(), double y = double(), double z = double());
    virtual ~point();

    double x() const;
    double y() const;
    double z() const;

    void x(double val);
    void y(double val);
    void z(double val);

    void set(double x, double y, double z);
    void zero();

    const double* c_data() const;

    point& operator= (const point& p);
    point& operator+=(const point& p);
    point& operator-=(const point& p);
    point& operator*=(double s);
    point& operator/=(double s);

    void normalise();
    void resize(double l);

    double length() const;
    double length_sq() const;

  protected:
    double data[3];
  };
}

util::point operator+(const util::point& a, const util::point& b);
util::point operator-(const util::point& a, const util::point& b);
util::point operator*(double s, const util::point& p);
util::point operator*(const util::point& p, double s);
util::point operator/(double s, const util::point& p);
util::point operator/(const util::point& p, double s);

bool operator==(const util::point& a, const util::point& b);
bool operator!=(const util::point& a, const util::point& b);

double      operator*(const util::point& a, const util::point& b);
util::point cross(const util::point& a, const util::point& b);
util::point proj(const util::point& a, const util::point& b);
double      proj_length(const util::point& a, const util::point& b);

double distance(const util::point& a, const util::point& b);
double distance_sq(const util::point& p, const util::point& b);

std::ostream& operator<<(std::ostream& os, const util::point& p);
std::istream& operator>>(std::istream& is, util::point& p);

#endif
